﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Xml.Linq;
using Medianamik.Core.Urls;
using StructureMap;

namespace Medianamik.Core.Redirect
{
    public class RedirectDictionary : KeyedCollection<string, RedirectDictionaryEntry>
    {
        private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
        //Voir http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

        public RedirectDictionary()
        {
            Initialize();
        }

        private void Initialize()
        {
            var redirects = ObjectFactory.GetInstance<IRedirectUrlRepository>().GetAllRedirect();
            var urlDico = new ObjectFactory<IUrlDictionary>().Get();

            foreach (var redirect in redirects)
            {
                var responseCode = redirect.ResponseCode;
                var redirectQS = redirect.QueryString;
                var redirect1 = redirect;
                var entries = urlDico.GetEntries(redirect.RedirectToNodeId, redirect.Culture)
                    .Select(e => new RedirectDictionaryEntry(redirect1.RedirectFrom, responseCode, e, redirectQS));
                entries.ForEach(e => { if (!Contains(GetKeyForItem(e))) Add(e); });
            }
        }

        public static RedirectDictionary Instance
        {
            get
            {
                return Singleton<RedirectDictionary>.Instance;
            }
        }

        public RedirectDictionaryEntry GetEntry(string pUri)
        {
            pUri = (pUri ?? string.Empty).ToLowerInvariant();
            _lock.EnterReadLock();
            try
            {
                if (this.Contains(pUri))
                {
                    return this[pUri];
                }
                return null;
            }
            finally
            {
                _lock.ExitReadLock();
            }
        }

        public bool ContainsUrl(string pUrl)
        {
            _lock.EnterReadLock();
            try
            {
                return Contains((pUrl ?? string.Empty).ToLowerInvariant());
            }
            finally
            {
                _lock.ExitReadLock();
            }
        }

        public void Reload()
        {
            _lock.EnterWriteLock();
            try
            {
                Clear();
                Initialize();
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }

        public ReadOnlyCollection<string> Domains
        {
            get
            {
                return new ReadOnlyCollection<string>(this.Select(e => e.UrlDictionaryEntry.Domain).Distinct().ToList());
            }
        }

        protected override string GetKeyForItem(RedirectDictionaryEntry item)
        {
            return item.RedirectFromUri.ToString().ToLowerInvariant();
        }

        public RedirectDictionaryEntry[] GetEntries(object pItemId, CultureInfo pCulture)
        {
            throw new NotImplementedException();
        }

        public void AddSafe(string pRedirectFromPath, Guid pRedirectToNodeId, string pAppendQS,
            CultureInfo pCulture, int pResponseCode)
        {
            var urlDico = new ObjectFactory<IUrlDictionary>().Get();
            var entries = urlDico.GetEntries(pRedirectToNodeId, pCulture)
                         .Select(e => new RedirectDictionaryEntry(pRedirectFromPath, pResponseCode, e, pAppendQS));

            entries.ForEach(e => { if (!Contains(GetKeyForItem(e))) this.Add(e); });
        }
    }

    public class Redirect
    {
        public int ResponseCode { get; set; }
        public string QueryString { get; set; }
        public string RedirectFrom { get; set; }
        public Guid RedirectToNodeId { get; set; }
        public CultureInfo Culture { get; set; }
    }
}
